<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>es6 类的混入mixin用法</title>
  <!-- 
  在JavaScript中，特别是使用ES6类时，混入（Mixin）是一种将多个对象的属性和方法合并到一个类中的技术。混入可以帮助我们在类之间共享功能，而无需使用继承。
  1. 混入的基本概念
  混入是一种设计模式，允许一个对象或类从多个来源获取功能。它通常用于避免多重继承的问题。

  2. 混入的实现方式
  在ES6中，混入通常通过函数来实现，这些函数将源对象的属性和方法复制到目标对象中。
  function mixin(target, ...sources) {
      Object.assign(target, ...sources);
  }

  // 示例源对象
  const canFly = {
      fly() {
          console.log('I can fly!');
      }
  };

  const canSwim = {
      swim() {
          console.log('I can swim!');
      }
  };

  // 目标类
  class Animal {
      constructor(name) {
          this.name = name;
      }
  }

  // 使用混入
  mixin(Animal.prototype, canFly, canSwim);

  const duck = new Animal('Duck');
  duck.fly(); // 输出: I can fly!
  duck.swim(); // 输出: I can swim!
  3. 使用类作为混入
  你也可以使用类作为混入的来源。可以通过继承和组合来实现更复杂的功能：
  class CanFly {
      fly() {
          console.log('I can fly!');
      }
  }

  class CanSwim {
      swim() {
          console.log('I can swim!');
      }
  }

  class Duck extends CanFly {
      constructor(name) {
          super();
          this.name = name;
      }
  }

  // 混入游泳功能
  Object.assign(Duck.prototype, CanSwim.prototype);

  const duck = new Duck('Duck');
  duck.fly(); // 输出: I can fly!
  duck.swim(); // 输出: I can swim!

  4. 注意事项
  - 属性冲突：当多个混入对象中存在相同属性时，后面的对象会覆盖前面的对象的属性。
  - 性能问题：频繁地使用混入可能会影响性能，特别是在大型应用中。
  - 可读性：过度使用混入可能会导致代码可读性降低，因此应谨慎使用。

  5. 结论
  混入是一种强大的工具，可以帮助我们构建灵活和可重用的代码。在使用混入时，应该注意其带来的复杂性和潜在问题，以确保代码的清晰和可维护性。
   -->
</head>
<body>

  <script>
    // JavaScript 只支持单继承, 不支持多继承, 但是可以通过混入(mixin)来实现多继承的效果
    // 混入是一种将多个对象合并为一个对象的技术, 可以将多个对象的属性和方法合并到一个对象中
    function mixinAnimal(BaseClass) {
      return class extends BaseClass {
        running() {
          console.log("running~")
        }
      };
    }

    function mixinRunner(BaseClass) {
      return class extends BaseClass {
        flying() {
          console.log("flying~")
        }
      }
    }
    
    const canFly = {
      fly() {
        console.log('I can fly!');
      }
    }

    class Cat extends mixinAnimal(mixinRunner(canFly)) {
    }

    const cat = new Cat();
    cat.fly(); // 输出: I can fly!
    cat.running(); // 输出: running~
    cat.flying(); // 输出: flying~
    
  </script>
  
</body>
</html>